/*
 * commons is a based project implemented
 * Copyright (C) 2024 Jasmine
 */
package com.commons.core.utils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Month;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;

/**
 * LocalDateTime工具类
 *
 * @author Jasmine
 * @version 1.0
 * @date 2021-11-30 8:36:36
 * @see LocalDateTimeEndUtils
 * @since JDK1.8
 */
public class LocalDateTimeEndUtils {
    /* public static void main(String[] args) {
        System.out.println("今天结束时间：" + endTimeToday());
        System.out.println("昨天结束时间：" + endTimeByDay(-1));
        System.out.println("明天结束时间：" + endTimeByDay(1));
    
        System.out.println("最近7天结束时间：" + endTimeLast7Days());
        System.out.println("最近30天天结束时间：" + endTimeLast30Days());
    
        System.out.println("本周结束时间：" + endTimeWeek());
        System.out.println("本月结束时间：" + endTimeMonth());
        System.out.println("本季度结束时间：" + endTimeQuarter());
        System.out.println("本半年结束时间：" + endTimeHalfYear());
        System.out.println("本年结束时间：" + endTimeYear());
        System.out.println("获取指定月份月最后一天：" + endTimeByMonth(LocalDate.of(2021, 11, 30)));
    
    
        System.out.println("最近一年结束时间：" + endTimeLast1Year());
        System.out.println("上周结束时间：" + endTimeLastWeek());
        System.out.println("上月结束时间：" + endTimeLastMonth());
        System.out.println("上季度结束时间：" + endTimeLastQuarter());
        System.out.println("上半年结束时间：" + endTimeLastHalfYear());
        System.out.println("上一年结束时间：" + endTimeLastYear());
        System.out.println("下周结束时间：" + endTimeNextWeek());
        System.out.println("下月结束时间：" + endTimeNextMonth());
        System.out.println("下季度结束时间：" + endTimeNextQuarter());
        System.out.println("下半年结束时间：" + endTimeNextHalfYear());
        System.out.println("下一年结束时间：" + endTimeNextYear());
    }*/

    /**
     * 今天结束时间
     */
    public static LocalDateTime endTimeToday() {
        return LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
    }

    /**
     * 当前时间结束 +- 天数 eg:昨天结束时间=endTimeByDay(-1)
     */
    public static LocalDateTime endTimeByDay(long amountToSubtract) {
        return LocalDateTime.of(LocalDate.now().plus(amountToSubtract, ChronoUnit.DAYS), LocalTime.MAX);
    }

    /**
     * 最近7天结束时间
     *
     * @return
     */
    public static LocalDateTime endTimeLast7Days() {
        return LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
    }

    /**
     * 最近30天结束时间
     *
     * @return
     */
    public static LocalDateTime endTimeLast30Days() {
        return LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
    }

    /**
     * 本周结束时间
     *
     * @return
     */
    public static LocalDateTime endTimeWeek() {
        LocalDate now = LocalDate.now();
        return LocalDateTime.of(now.plusDays(7 - now.getDayOfWeek().getValue()), LocalTime.MAX);
    }

    /**
     * 本月结束时间
     *
     * @return
     */
    public static LocalDateTime endTimeMonth() {
        return LocalDateTime.of(LocalDate.now().with(TemporalAdjusters.lastDayOfMonth()), LocalTime.MAX);
    }

    /**
     * 本季度结束时间
     *
     * @return
     */
    public static LocalDateTime endTimeQuarter() {
        LocalDate now = LocalDate.now();
        Month month = Month.of(now.getMonth().firstMonthOfQuarter().getValue()).plus(2L);
        return LocalDateTime.of(LocalDate.of(now.getYear(), month, month.length(now.isLeapYear())), LocalTime.MAX);
    }

    /**
     * 本半年结束时间
     *
     * @return
     */
    public static LocalDateTime endTimeHalfYear() {
        LocalDate now = LocalDate.now();
        Month month = (now.getMonthValue() > 6) ? Month.DECEMBER : Month.JUNE;
        return LocalDateTime.of(LocalDate.of(now.getYear(), month, month.length(now.isLeapYear())), LocalTime.MAX);
    }

    /**
     * 本年结束时间
     *
     * @return
     */
    public static LocalDateTime endTimeYear() {
        return LocalDateTime.of(LocalDate.now().with(TemporalAdjusters.lastDayOfYear()), LocalTime.MAX);
    }

    /**
     * 获取指定月份月最后一天
     */
    public static LocalDateTime endTimeByMonth(LocalDate localDate) {
        return LocalDateTime.of(localDate.with(TemporalAdjusters.lastDayOfMonth()), LocalTime.MAX);
    }

    /**
     * 最近一年结束时间
     *
     * @return
     */
    public static LocalDateTime endTimeLast1Year() {
        return LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
    }

    /**
     * 上周结束时间
     *
     * @return
     */
    public static LocalDateTime endTimeLastWeek() {
        LocalDate lastWeek = LocalDate.now().minus(1L, ChronoUnit.WEEKS);
        return LocalDateTime.of(lastWeek.plusDays(7 - lastWeek.getDayOfWeek().getValue()), LocalTime.MAX);
    }

    /**
     * 上月结束时间
     *
     * @return
     */
    public static LocalDateTime endTimeLastMonth() {
        return LocalDateTime.of(LocalDate.now().minus(1L, ChronoUnit.MONTHS).with(TemporalAdjusters.lastDayOfMonth()),
            LocalTime.MAX);
    }

    /**
     * 上季度结束时间
     *
     * @return
     */
    public static LocalDateTime endTimeLastQuarter() {
        LocalDate now = LocalDate.now();
        Month firstMonthOfQuarter = Month.of(now.getMonth().firstMonthOfQuarter().getValue());
        Month firstMonthOfLastQuarter = firstMonthOfQuarter.minus(1L);
        int yearOfLastQuarter = firstMonthOfQuarter.getValue() < 4 ? now.getYear() - 1 : now.getYear();
        return LocalDateTime.of(
            LocalDate.of(yearOfLastQuarter, firstMonthOfLastQuarter, firstMonthOfLastQuarter.maxLength()),
            LocalTime.MAX);
    }

    /**
     * 上半年结束时间
     *
     * @return
     */
    public static LocalDateTime endTimeLastHalfYear() {
        LocalDate now = LocalDate.now();
        int lastHalfYear = (now.getMonthValue() > 6) ? now.getYear() : now.getYear() - 1;
        Month lastMonthOfLastHalfYear = (now.getMonthValue() > 6) ? Month.JUNE : Month.DECEMBER;
        return LocalDateTime.of(
            LocalDate.of(lastHalfYear, lastMonthOfLastHalfYear, lastMonthOfLastHalfYear.maxLength()), LocalTime.MAX);
    }

    /**
     * 上一年结束时间
     *
     * @return
     */
    public static LocalDateTime endTimeLastYear() {
        return LocalDateTime.of(LocalDate.now().minus(1L, ChronoUnit.YEARS).with(TemporalAdjusters.lastDayOfYear()),
            LocalTime.MAX);
    }

    /**
     * 下周结束时间
     *
     * @return
     */
    public static LocalDateTime endTimeNextWeek() {
        LocalDate nextWeek = LocalDate.now().plus(1L, ChronoUnit.WEEKS);
        return LocalDateTime.of(nextWeek.plusDays(7 - nextWeek.getDayOfWeek().getValue()), LocalTime.MAX);
    }

    /**
     * 下月结束时间
     *
     * @return
     */
    public static LocalDateTime endTimeNextMonth() {
        return LocalDateTime.of(LocalDate.now().plus(1L, ChronoUnit.MONTHS).with(TemporalAdjusters.lastDayOfMonth()),
            LocalTime.MAX);
    }

    /**
     * 下季度结束时间
     *
     * @return
     */
    public static LocalDateTime endTimeNextQuarter() {
        LocalDate now = LocalDate.now();
        Month firstMonthOfQuarter = Month.of(now.getMonth().firstMonthOfQuarter().getValue());
        Month firstMonthOfNextQuarter = firstMonthOfQuarter.plus(5L);
        int yearOfNextQuarter = firstMonthOfQuarter.getValue() > 9 ? now.getYear() + 1 : now.getYear();
        return LocalDateTime.of(
            LocalDate.of(yearOfNextQuarter, firstMonthOfNextQuarter, firstMonthOfNextQuarter.maxLength()),
            LocalTime.MAX);
    }

    /**
     * 上半年结束时间
     *
     * @return
     */
    public static LocalDateTime endTimeNextHalfYear() {
        LocalDate now = LocalDate.now();
        int lastHalfYear = (now.getMonthValue() > 6) ? now.getYear() + 1 : now.getYear();
        Month lastMonthOfNextHalfYear = (now.getMonthValue() > 6) ? Month.JUNE : Month.DECEMBER;
        return LocalDateTime.of(
            LocalDate.of(lastHalfYear, lastMonthOfNextHalfYear, lastMonthOfNextHalfYear.maxLength()), LocalTime.MAX);
    }

    /**
     * 下一年结束时间
     *
     * @return
     */
    public static LocalDateTime endTimeNextYear() {
        return LocalDateTime.of(LocalDate.now().plus(1L, ChronoUnit.YEARS).with(TemporalAdjusters.lastDayOfYear()),
            LocalTime.MAX);
    }
}
